/**
 * 
 */
package com.eis.function.in;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.eis.function.in.base.BaseTask;
import com.eis.function.out.rule.RuleEngine;
import com.eis.function.out.rule.StatusRuleResult;
import com.eis.function.out.rule.model.StatusRules;
import com.eis.persist.dao.FunctionDAO;
import com.eis.persist.dao.impl.FunctionDAOImpl;
import com.eis.persist.model.function.PersistFunction;
import com.eis.persist.model.function.PersistFunctionSchema;
import com.eis.persist.model.function.PersistFunctionStatusRule;
import com.eis.thirdsys.connector.ThirdSysConnectorFactory;
import com.eis.thirdsys.connector.datatype.DataTypeList;

/**
 * @author sh-panwei01
 *
 */
public class FunctionStatusUpdater extends BaseTask {
	private static final Logger logger = LoggerFactory.getLogger(FunctionStatusUpdater.class);
	private RuleEngine statusRuleEngine;

	public void setStatusRuleEngine(RuleEngine statusRuleEngine) {
		this.statusRuleEngine = statusRuleEngine;
	}

	/* (non-Javadoc)
	 * @see com.eis.in.EisTimerTask#runTask()
	 */
	@Override
	public void runTask() {
		// UserDAO userDAO = new UserDAOImpl(this.dataSource);
		FunctionDAO functionDAO = new FunctionDAOImpl(this.dataSource);
		// get all functions need run rule
		Map<Integer, PersistFunction> sapFunctions = functionDAO.loadALlEnabledFunctions();
		
		List<PersistFunctionStatusRule> persistFunctionStatusRules = functionDAO.loadAllFunctionStatusRules();
		
		Map<Integer, ThirdSysConnectorFactory> bizsysIdThirdSysConnectorFactoryMap = new HashMap<Integer, ThirdSysConnectorFactory>();
		Map<String, ThirdSysConnectorFactory> functionIdThirdSysConnectorFactoryMap = new HashMap<String, ThirdSysConnectorFactory>();
		
		

		try {
			for (PersistFunction function : sapFunctions.values()) {
				int bizSysId = function.getBizSystem().getId();
				ThirdSysConnectorFactory thirdSysConnectorFactory = bizsysIdThirdSysConnectorFactoryMap.get(bizSysId);
				if (thirdSysConnectorFactory == null) {
					thirdSysConnectorFactory = new ThirdSysConnectorFactory(function.getBizSystem().getConnectorStaticsClassName());
					bizsysIdThirdSysConnectorFactoryMap.put(bizSysId, thirdSysConnectorFactory);
				}
				
				functionIdThirdSysConnectorFactoryMap.put(function.getFunctionID(), thirdSysConnectorFactory);
			}
		} catch (Exception e) {
			logger.error("", e);
			return;
		}
		if (persistFunctionStatusRules != null) {
			Date currentTime = new Date();
			long currentTimeMill = currentTime.getTime();
			
			statusRuleEngine.setStatusList(functionDAO.loadFunctionStatuses());
			for (PersistFunctionStatusRule persistFunctionStatusRule : persistFunctionStatusRules) {
				try {
					statusRuleEngine.setupRuleEngine(null, persistFunctionStatusRule.getRulexml());
					
					StatusRules statusRules = statusRuleEngine.getStatusRules();
					String functionID = persistFunctionStatusRule.getFunctionID();
					Date effectTime = new Date(currentTimeMill - statusRules.getEffectTime());
					List<Map<String, Object>> functionData = functionDAO.getFunctionData(functionID, effectTime);
					
					// load schema
					List<PersistFunctionSchema> schemaList = functionDAO.getFunctionSchemaByFunctionId(functionID);
					Map<String, String> dataTypeMap = new HashMap<String, String>();
					for (PersistFunctionSchema oneSchema : schemaList) {
						dataTypeMap.put(oneSchema.getFieldName(), oneSchema.getFieldType());
					}
					ThirdSysConnectorFactory thirdSysConnectorFactory = functionIdThirdSysConnectorFactoryMap.get(persistFunctionStatusRule.getFunctionID());
					
					if (thirdSysConnectorFactory != null) { 
						DataTypeList functionDataTypeList = thirdSysConnectorFactory.newDataTypeList();
						List<StatusRuleResult> ruleResult = statusRuleEngine.runStatusRule(functionData, 
								dataTypeMap, 
								currentTime, 
								functionDataTypeList);
						
						// update function status
						if (ruleResult != null && ruleResult.size() > 0) {
							int updatedRows = functionDAO.batchUpdateFunctionStatus(ruleResult, functionID);
							logger.info("function status updated, function ID: " + functionID + " Rows: " + updatedRows);
						}
					}
				} catch (Throwable t) {
					logger.error("Exception when running rule: " + persistFunctionStatusRule.getId() 
							+ " for function: " + persistFunctionStatusRule.getFunctionID(), t);
				}
			}
		}
		
	}
}
